package org.god.batis.core;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.god.batis.utils.Resources;

import javax.sql.DataSource;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SqlSessionFactoryBuilder {
    public SqlSessionFactoryBuilder() {
    }

    /**
     * 解析xml文件
     *
     * @param inputStream
     * @return
     */
    public SqlSessionFactory build(InputStream inputStream) {
        Transaction transaction = null;
        Map<String, MappedStatement> mappedStatementMap = new HashMap<>();
        try {
            //解析逻辑请查看pase-xml-by-dom4j 模块
            SAXReader saxReader = new SAXReader();
            InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
            Document document = saxReader.read(resourceAsStream);
            String xpath = "/configuration/environments";
            Element element = (Element) document.selectSingleNode(xpath);
            String defaultEnvironmentId = element.attributeValue("default");
            xpath = "/configuration/environments/environment[@id='" + defaultEnvironmentId + "']";
            //获取到指定的环境配置
            Element environment = (Element) document.selectSingleNode(xpath);
            Element transactionManager = environment.element("transactionManager");
            //事务管理器类型
            String transactionType = transactionManager.attributeValue("type");
            //数据源类型的标签
            Element dataSourceElt = environment.element("dataSource");
            DataSource dataSource = getDataSource(dataSourceElt);
            transaction = getTransaction(dataSource, transactionManager);
            //开始解析sql的xml文件
            xpath = "/configuration/mappers";
            Element mappersElement = (Element) document.selectSingleNode(xpath);
            mappedStatementMap = getMappedStatementMap(mappersElement);
        } catch (Exception e) {
            e.printStackTrace();
        }
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactory(transaction, mappedStatementMap);
        return sqlSessionFactory;
    }

    private Map<String, MappedStatement> getMappedStatementMap(Element mappersElement) {
        Map<String, MappedStatement> mappedStatementMap = new HashMap<>();
        List<Element> mapperElements = mappersElement.elements();
        SAXReader saxReader = new SAXReader();
        mapperElements.forEach(mapperItem -> {
            //获取配置的mapper的文件名称
            String resource = mapperItem.attributeValue("resource");
            try {
                Document tempDocument = saxReader.read(Resources.getResourceAsStream(resource));
                String tempXpath = "/mapper";
                Element mapperRootElement = (Element) tempDocument.selectSingleNode(tempXpath);
                //获取mapper根标签的namespace属性
                String namespace = mapperRootElement.attributeValue("namespace");
                List<Element> sqlElements = mapperRootElement.elements();
                sqlElements.forEach(sqlItem -> {
                    String id = sqlItem.attributeValue("id");
                    String resultType = sqlItem.attributeValue("resultType");
                    String sql = sqlItem.getTextTrim();
                    MappedStatement mappedStatement = new MappedStatement(sql, resultType);
                    mappedStatementMap.put(namespace + id, mappedStatement);
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        return mappedStatementMap;
    }

    /**
     * 获取事务管理器
     * @param dataSource
     * @param transactionManager
     * @return
     */
    private Transaction getTransaction(DataSource dataSource, Element transactionManager) {
        Transaction transaction = null;
        //事务管理器类型
        String transactionType = transactionManager.attributeValue("type");
        if ("JDBC".equals(transactionType)) {
            transaction = new JdbcTransaction(dataSource, false);
        } else if ("MANAGED".equals(transactionType)) {

        }
        return transaction;
    }

    /**
     * 获取数据源
     * @param dataSourceElt
     * @return
     */
    private DataSource getDataSource(Element dataSourceElt) {
        String dataSourceType = dataSourceElt.attributeValue("type");
        DataSource dataSource = null;
        if ("UNPOOLED".equals(dataSourceType)) {
            List<Element> propertyElements = dataSourceElt.elements();
            Map<String, String> mapJdbc = new HashMap<>();
            propertyElements.forEach(propertyItem -> {
                String name = propertyItem.attributeValue("name");
                String value = propertyItem.attributeValue("value");
                mapJdbc.put(name, value);
            });
            dataSource = new UnPooledDataSource(mapJdbc.get("driver"), mapJdbc.get("url"),
                    mapJdbc.get("username"), mapJdbc.get("password"));
        } else if ("POOLED".equals(dataSourceType)) {

        } else if ("JNDI".equals(dataSourceType)) {

        }
        return dataSource;
    }
}
